/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "iccreader_srv_stub.h"
#include <string.h>
#include "message_option.h"
#include "message_parcel.h"
#include "iccreader_hilog.h"
#include "iccreader_common.h"
#include "iccreader_errors.h"

namespace SwanLink {
namespace Finance {
int IccreaderSrvStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
{
    ICCREADER_HILOGD(ICCREADER_SRV, "cmd = %{public}d, flags = %{public}d", code, option.GetFlags());
    std::u16string descriptor = IccreaderSrvStub::GetDescriptor();
    std::u16string remoteDescriptor = data.ReadInterfaceToken();
    if (descriptor != remoteDescriptor) {
        ICCREADER_HILOGE(ICCREADER_SRV, "Descriptor is not matched");
        return ERR_NAME_NOT_FOUND;
    }

    return CheckRequestCode(code, data, reply, option);
}

int32_t IccreaderSrvStub::CheckRequestCode(const uint32_t code, MessageParcel& data, MessageParcel& reply,
    MessageOption& option)
{
    switch (code) {
        
        case static_cast<int>(IIccreaderSrv::ICCREADER_GETDEVICEINFO): {
            return GetDeviceInfoStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_ICCIOCTRL): {
            return IccIOCtrlStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_APDUCOMMAND): {
            return ApduCommandStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_CARDSEARCH): {
            return CardSearchStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_CARDSTOPSEARCH): {
            return CardStopSearchStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_RFCARDACTIVE): {
            return RfCardActiveStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_RFCARDDORMANCY): {
            return RfCardDormancyStub(data,reply,option);
        }
        case static_cast<int>(IIccreaderSrv::ICCREADER_SCANDATA): {
            return ScanDataStub(data,reply,option);
        }
        default: {
            return CashDeviceService::OnRemoteRequest(code, data, reply, option);
        }

    }
    return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
}


int32_t IccreaderSrvStub::GetDeviceInfoStub(MessageParcel& data, MessageParcel& reply, MessageOption& option)
{
    int fd = -1;
    DeviceInfo devInfo;

    READ_PARCEL_WITH_RET(data, Int32, fd, E_READ_PARCEL_ERROR);

    int result = GetDeviceInfo(fd, devInfo);
    WRITE_BUFFER_WITH_RET(data, DeviceInfo, &devInfo, sizeof(devInfo), -1);  
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t IccreaderSrvStub::IccIOCtrlStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;
    int type = 0;
    int value = -1;

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, type, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, value, E_READ_PARCEL_ERROR);

    int result = IccIOCtrl(fd, (IOType)type, value);
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t IccreaderSrvStub::ApduCommandStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;
    int type;
    int len = 0;
    uint8_t* cmd = NULL;
    uint8_t cmd_out[256];

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data,Int32, type, E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data, Int32, len, E_READ_PARCEL_ERROR);
    if (len > 0)
        READ_BUFFER_WITH_RET(data, uint8_t, cmd, len, E_READ_PARCEL_ERROR);

    int result = ApduCommand(fd, (IOType)type, len, cmd, cmd_out);
    
    WRITE_PARCEL_WITH_RET(reply,Int32,result,E_WRITE_PARCEL_ERROR);
    if (result > 0)
        WRITE_BUFFER_WITH_RET(reply, uint8_t, cmd_out, result, -1); 

    return ERR_OK;
}
int32_t IccreaderSrvStub::CardSearchStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;
    int timeout = -1;

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);
    READ_PARCEL_WITH_RET(data,Int32,timeout,E_READ_PARCEL_ERROR);
    sptr<IRemoteObject> remote = data.ReadRemoteObject();
    if (remote != nullptr) {
        proxy_ = iface_cast<IccReaderObserverProxy>(remote);
    } else {
        proxy_ = nullptr;
    }

    int result = CardSearch(fd, timeout, proxy_);
    WRITE_PARCEL_WITH_RET(reply,Int32,result,E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t IccreaderSrvStub::CardStopSearchStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);

    int result = CardStopSearch(fd);
    WRITE_PARCEL_WITH_RET(reply,Int32,result,E_WRITE_PARCEL_ERROR);
    proxy_ = nullptr;
    return ERR_OK;
}
int32_t IccreaderSrvStub::RfCardActiveStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;
    RfCardInfo cardInfo;

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);

    int result = RfCardActive(fd, cardInfo);
    WRITE_PARCEL_WITH_RET(reply,Int32,result,E_WRITE_PARCEL_ERROR);
    WRITE_BUFFER_WITH_RET(data, RfCardInfo, &cardInfo, sizeof(cardInfo), E_WRITE_PARCEL_ERROR); 

    return ERR_OK;
}
int32_t IccreaderSrvStub::RfCardDormancyStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;

    READ_PARCEL_WITH_RET(data,Int32,fd,E_READ_PARCEL_ERROR);

    int result = RfCardDormancy(fd);
    WRITE_PARCEL_WITH_RET(reply,Int32,result,E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}
int32_t IccreaderSrvStub::ScanDataStub(MessageParcel& data,MessageParcel& reply,MessageOption& option)
{
    int fd = -1;
    DeviceConfig config;
    ResultData out;

    READ_PARCEL_WITH_RET(data, Int32, fd, E_READ_PARCEL_ERROR);
    READ_BUFFER_WITH_COPY(data,  DeviceConfig,  &config, sizeof(DeviceConfig));

    int result = ScanData(fd, config, out);
    WRITE_BUFFER_WITH_RET(reply, ResultData, &out, sizeof(out), E_WRITE_PARCEL_ERROR); 
    WRITE_PARCEL_WITH_RET(reply, Int32, result, E_WRITE_PARCEL_ERROR);

    return ERR_OK;
}

} // namespace Finance
} // namespace SwanLink
